<?php
namespace app\api\services;

use app\api\consDir\ErrorConst;
use app\common\libs\Singleton;
use app\common\models\Coupon;
use app\common\models\CouponGoods;
use app\common\models\CouponMember;
use app\common\models\Member\Member;
use app\common\models\Member\MemberCoupon;
use app\common\models\Shop\Shop;
use app\common\models\Supply\SupplyGoods;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;

class CouponService
{
    use Singleton;

    public function updateCouponInfo($couponId): bool
    {
        if (empty($couponId)) {
            return false;
        }
        $where = [
            ['id', 'in', $couponId],
        ];
        CouponMember::getInstance()->where($where)->update(['status' => 1, 'update_at' => date('Y-m-d H:i:s')]);
        return true;
    }

    /**
     * 获取优惠的商品金额，商品是否满足条件已在调用该放之前判断
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function getCouponPrice(&$priceInfo, $couponId, $userId)
    {
        //$allPrice = $priceInfo['allList']['pay_price'];
        //$priceInfo['allList']['pay_price'] = bcsub($priceInfo['allList']['pay_price'], $couponAmount, 2);
        //$priceInfo['allList']['sale'] = $couponAmount;
        //dump($priceInfo);die;
        $priceInfo['allList']['coupon_id'] = $couponId;

        $couponLi = $this->getCouponInfo($couponId, $userId);
        // 优惠券优化总额
        [$couponMoney, $pSale, $shopSale] = $this->calCouponPrice(
            $priceInfo['allList']['pay_price'],
            $couponId,
            $userId,
            $couponLi);

        $priceInfo['allList']['pay_price'] = bcsub($priceInfo['allList']['pay_price'], bcadd($couponMoney,0,2), 2);
        $priceInfo['allList']['sale']      = bcadd($priceInfo['allList']['sale'], $couponMoney,2);

        $ids             = [];
        $subOrderSaleMap = [];

        $len = count($priceInfo['goodsPriceList']);

        $perPSale          = floatval($pSale > 0 ? number_format($pSale / $len, 2, '.', '') : 0);
        $perSSale          = floatval($shopSale > 0 ? number_format($shopSale / $len, 2, '.', '') : 0);
        $shop_sale_sum     = 0;
        $platform_sale_sum = 0;
        foreach ($priceInfo['goodsPriceList'] as $i => &$vo) {
            $shopId = $vo['shop_id'];
            $ids[]  = $shopId;

            if ($i == ($len - 1)) {
                $vo['platform_sale'] = bcsub($pSale , $platform_sale_sum,2);
                $vo['shop_sale']     = bcsub($shopSale , $shop_sale_sum,2);
            } else {
                $vo['platform_sale'] = bcadd($perPSale,0,2);
                $vo['shop_sale']     = bcadd($perSSale,0,2);
            }
            $vo['sale']      = bcadd($vo['sale'] + $vo['platform_sale'] , $vo['shop_sale'],2);
            $vo['pay_price'] = bcsub($vo['pay_price'],$vo['sale'],2);
            $shop_sale_sum += $perSSale;
            $platform_sale_sum += $perPSale;

            if (isset($subOrderSaleMap[$shopId])) {
                $subOrderSaleMap[$shopId]['pay_price'] += $vo['pay_price'];
                $subOrderSaleMap[$shopId]['sale'] += $vo['sale'];
                $subOrderSaleMap[$shopId]['shop_sale'] += $vo['shop_sale'];
                $subOrderSaleMap[$shopId]['platform_sale'] += $vo['platform_sale'];
            } else {
                $subOrderSaleMap[$shopId] = [
                    'pay_price'     => $vo['pay_price'],
                    'sale'          => $vo['sale'],
                    'shop_sale'     => $vo['shop_sale'],
                    'platform_sale' => $vo['platform_sale'],
                ];
            }
        }
        // var_dump($priceInfo['allList']['pay_price']);exit;

        // echo json_encode($priceInfo['goodsPriceList'], 320);exit;
        // var_dump(count($priceInfo['goodsPriceList']));exit;
        // foreach ($priceInfo['goodsPriceList'] as $val2) {
        //     $shopId = $val2['shop_id'];
        //     $ids[]  = $shopId;
        //     if (isset($subOrderSaleMap[$shopId])) {
        //         $subOrderSaleMap[$shopId]['pay_price'] += $val2['pay_price'];
        //         $subOrderSaleMap[$shopId]['sale'] += $val2['sale'];
        //         $subOrderSaleMap[$shopId]['shop_sale'] += $val2['shop_sale'];
        //         $subOrderSaleMap[$shopId]['platform_sale'] += $val2['platform_sale'];
        //     } else {
        //         $subOrderSaleMap[$shopId] = [
        //             'pay_price'     => $val2['pay_price'],
        //             'sale'          => $val2['sale'],
        //             'shop_sale'     => $val2['shop_sale'],
        //             'platform_sale' => $val2['platform_sale'],
        //         ];
        //     }
        // }

        // echo json_encode($priceInfo['goodsPriceList'], 320);exit;
        // var_dump($ids, $subOrderSaleMap, count($priceInfo['goodsPriceList']));exit;
        foreach ($priceInfo['shopPriceList'] as &$val3) {
            $shopId = $val3['shop_id'];
            if ( ! isset($val3['shop_sale'])) {
                $val3['shop_sale'] = 0;
            }
            if ( ! isset($val3['platform_sale'])) {
                $val3['platform_sale'] = 0;
            }
            if (isset($subOrderSaleMap[$shopId])) {
                $val4 = $subOrderSaleMap[$shopId];
                // var_dump($val);exit;
                $val3['pay_price']     = bcadd($val4['pay_price'],0,2);
                $val3['sale']          = bcadd($val4['sale'],0,2);
                $val3['shop_sale']     = bcadd($val4['shop_sale'],2);
                $val3['platform_sale'] = bcadd($val4['platform_sale'],0,2);
            }
        }
        /*
            foreach ($priceInfo['shopPriceList'] as &$val) {
                $percent = bcdiv($val['pay_price'], $allPrice, 2);
                $thisCouponAmount = bcmul($couponAmount, $percent, 2);
                $val['pay_price'] = bcsub($val['pay_price'], $thisCouponAmount, 2);
                $val['sale'] = $thisCouponAmount;
            }

            foreach ($priceInfo['goodsPriceList'] as &$val) {
                $percent = bcdiv($val['pay_price'], $allPrice, 2);
                $thisCouponAmount = bcmul($couponAmount, $percent, 2);
                $val['pay_price'] = bcsub($val['pay_price'], $thisCouponAmount, 2);
                $val['sale'] = $thisCouponAmount;
            }*/

    }

    /**
     * 计算优惠券优化金额（先折扣，再满减；满减在折扣的基础上判断)
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function calCouponPrice($money, $couponId, $userId, $couponLi = [])
    {
        if (empty($couponLi)) {
            // 先折扣，后满减；先商家后平台；
            $couponLi = $this->getCouponInfo($couponId, $userId);
        }
        $discount     = 1;
        $platformSale = 0;
        $shopSale     = 0;

        // 商家折扣
        $discountShop = 1;
        foreach ($couponLi as $v) {
            //优惠券类型(10满减券 20折扣券)
            if ($v['couponType'] == 20) {
                $discount *= $v['discount'] * 0.01;

                if ( ! empty($v['shopId'])) {
                    $discountShop *= $v['discount'] * 0.01;
                }
            }
        }
        $discountAmount = $money * $discount; // 折扣后的金额

        $couponMoney = $money * (1 - $discount); // 总的折扣后的优惠金额
        $shopSale    = $money * (1 - $discountShop); // 商家的折扣后的金额

        foreach ($couponLi as $v) {
            //优惠券类型(10满减券 20折扣券)
            if ($v['couponType'] == 10) {
                if ($discountAmount >= $v['minPrice']) {
                    $couponMoney += $v['reducePrice'];
                    if ( ! empty($v['shopId'])) {
                        $shopSale += $v['reducePrice'];
                    }
                }
            }
        }
        // 先折扣，再满减
        $sale = max($couponMoney, 0);
        return [
            $sale, // 总的优惠金额
            $sale - $shopSale, // 平台优惠金额
            $shopSale, // 商家优惠金额
        ];
    }

    /**
     * @param $userId
     * @return int
     * @throws DbException
     */
    public function getCouponInfoCount($userId): int
    {
        $where = [
            ['user_id', '=', $userId],
            ['status', '=', 0],
            ['end_at', '>', date('Y-m-d H:i:s')],
            ['deleted', '=', 0],
        ];
        return MemberCoupon::getInstance()->where($where)->count('id');
    }

    /**
     * @param $cid
     * @param $userId
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getCouponInfo($cid, $userId): array
    {
        $where = [
            ['id', 'in', $cid],
            ['user_id', '=', $userId],
            ['end_time', '>', date('Y-m-d H:i:s')],
            ['status', '=', 0],
            ['deleted', '=', 0],
        ];
        $return = CouponMember::getInstance()
            ->where($where)
        // 先折扣，后满减；先商家后平台；
            ->order('coupon_type desc, shop_id desc, id desc')
            ->select();
        // echo CouponMember::getlastsql();exit;
        return empty($return) ? [] : $return->toArray();
    }

    /**
     * @throws DbException
     */
    public function autoRelease($uid, $vo): array
    {
        $end_time   = date('Y-m-d 23:59:59', strtotime("+ 3000days"));
        $nowDt      = date('Y-m-d H:i:s');
        $expireType = $vo['expireType'];
        //expire_type 到期类型(10领取后生效 20固定时间 30 长期有效)
        if ($expireType == 20) {
            $endTme = strtotime($vo['endTime']);
            if ($endTme < time()) {
                return [
                    'id'    => 0,
                    'code'  => ErrorConst::QUERY_NOT_EXIST,
                    'error' => '优惠券已过期',
                ];
                // CommonUtil::throwException(
                //     ErrorConst::QUERY_NOT_EXIST,
                //     '优惠券已过期');
            }
            $end_time = date('Y-m-d 23:59:59', $endTme);
        } elseif ($expireType == 10) {
            $end_time = date('Y-m-d 23:59:59', strtotime("+ {$vo['expireDay']}days"));
        } elseif ($expireType == 30) {
        }
        // 发放总数量(-1为不限制)
        $total_num = $vo['totalNum'] ?? -1;
        if ($total_num > -1) {
            $count = CouponMember::getInstance()->where('deleted', 0)
                ->where('coupon_id', $vo['id'])
                ->count();
            if ($count >= $total_num) {
                return [
                    'id'    => 0,
                    'code'  => ErrorConst::COUPON_ERROR,
                    'error' => '已达到发放总数量',
                ];
                // CommonUtil::throwException(
                //     ErrorConst::COUPON_ERROR,
                //     '已达到发放总数量');
            }
        }

        // 每位用户最大领取数量（0表示不限制）
        $receive_limit = $vo['receiveLimit'];
        if ($receive_limit > 0) {
            $count = CouponMember::getInstance()->where('deleted', 0)
                ->where('coupon_id', $vo['id'])
                ->where('user_id', $uid)
                ->count();
            if ($count >= $receive_limit) {
                return [
                    'id'    => 0,
                    'code'  => ErrorConst::COUPON_ERROR,
                    'error' => '已达到领取上限',
                ];
            }
        }
        $startTime = strtotime($vo['startTime']);
        if (empty($startTime)) {
            $startTime = time();
        }
        $id = 0;
        CouponMember::getInstance()->startTrans();
        try {
            Coupon::getInstance()->where('id', $vo['id'])
                ->inc('receive_num', 1)
                ->update();
            $id = CouponMember::getInstance()->insertGetId([
                'user_id'        => $uid,
                'coupon_id'      => $vo['id'],
                'coupon_title'   => $vo['couponTitle'],
                'coupon_type'    => $vo['couponType'],
                'reduce_price'   => $vo['reducePrice'],
                'discount'       => $vo['discount'],
                'min_price'      => $vo['minPrice'],
                'expire_type'    => $vo['expireType'],
                'expire_day'     => $vo['expireDay'],
                'start_time'     => date('Y-m-d H:i:s', $startTime),
                'end_time'       => $end_time,
                'use_scene'      => $vo['useScene'] ?? 0,
                'apply_range'    => $vo['applyRange'] ?? 10,
                'shop_id'        => $vo['shopId'],
                'status'         => 0,
                'multiple'       => $vo['multiple'],
                'multiple_other' => $vo['multipleOther'],
                'shop_type'      => $vo['shopId'] > 0 ? $vo['shopType'] : 3,
                'create_at'      => $nowDt,
            ]);
        } catch (\Exception $e) {
            \think\facade\Log::error($e->getMessage());
            CouponMember::getInstance()->rollback();
            $err = '系统错误';
            // $err = $err . $e->getMessage();
            return [
                'id'    => $id,
                'code'  => ErrorConst::SYSTEM_ERROR,
                'error' => $err,
            ];
        }
        CouponMember::getInstance()->commit();
        return ['id' => $id, 'error' => '', 'code' => 0];
    }

    public function checkApplyRange($couponId, $goodsSource, $goodsId, $included = 1)
    {
        $count = CouponGoods::where('deleted', 0)
            ->where('source', $goodsSource)
            ->where('coupon_id', $couponId)
            ->where('goods_id', $goodsId)
            ->count();
        if ($included == 1) {
            return $count > 0 ? true : false;
        } else {
            return $count > 0 ? false : true;
        }
    }

    /**
     * 参与买社区经营权会员，自动赠送相相应优惠券
     * 具体规则：买社区经营权，找到最近一层服务商，若服务商开了店铺 ，直接赠送商家优惠券
     * 若最近服务商未开店铺，不赠送
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function sendCoupon($userId): bool
    {
        $inviteIds = Member::getInstance()->where('id', $userId)->value('invite_ids');
        $idArr     = explode('-', $inviteIds);
        $where     = [
            ['id', 'in', $idArr],
            ['is_partner', '=', 1],
            ['is_shop', '=', 1],
            ['deleted', '=', 0],
        ];
        $serviceId = Member::getInstance()->where($where)->order('id desc')->value('id');
        if (empty($serviceId)) {
            return false;
        }
        $shopId = Shop::getInstance()->where('user_id', $serviceId)->value('id');
        if (empty($shopId)) {
            return false;
        }
        $where = [
            ['status', '=', 1],
            ['deleted', '=', 0],
            ['shop_id', '=', $shopId],
            ['use_scene', '=', 10],
        ];
        $coupon = Coupon::getInstance()->where($where)->select();
        if (empty($coupon)) {
            return false;
        }
        foreach ($coupon as $v) {
            $this->autoRelease($userId, $v);
        }
        return true;
    }

    /**
     * 下单的时候检查优惠券（有效期等）有效性
     * @param  [type]  $couponInfo [description]
     * @param  integer $source     [description]
     * @param  [type]  $goodsList  [description]
     * @return [type]              [description]
     */
    public function checkOrderCoupon($couponInfo, $source = 1, $goodsList): bool
    {
        if (empty($couponInfo)) {
            return false;
        }
        $isCan = true;
        $now   = time();
        foreach ($couponInfo as $v) {
            $startTime = strtotime($v['startTime']);
            $endTime   = strtotime($v['endTime']);
            if ($now > $endTime || $now < $startTime) {
                return false;
            }
            // 供应商商品不能使用商家优惠券
            if ($source == 2 && $v['shopId'] > 0) {
                return false;
            }
            // 适用范围 10全部商品 20指定商品 30排除商品
            if ($v['applyRange'] != 10) {
                //商品来源：1 日兮香商品(商家/平台自建商品) 2 怡亚通商品
                $goodsIdArr = CouponGoods::getInstance()
                    ->where('deleted', 0)
                    ->where('source', $source)
                    ->where('coupon_id', $v['couponId'])
                    ->column('goods_id');
                $isFlag = false;
                if ($source == 1) {
                    foreach ($goodsList as $vv) {
                        foreach ($vv['goodsInfo'] as &$vvv) {
                            $vvv['goodsId'] = $vvv['id'];
                            if (in_array($vvv['goodsId'], $goodsIdArr)) {
                                $isFlag = true;
                            }
                        }
                    }
                } elseif ($source == 2) {
                    foreach ($goodsList as $vv) {
                        $goodsId = SupplyGoods::getInstance()->where('spu_id', $vv['spuId'])->value('id');
                        if (in_array($goodsId, $goodsIdArr)) {
                            $isFlag = true;
                        }
                    }
                }
                if ( ! $isFlag) {
                    $isCan = false;
                    break;
                }
            }
        }
        return $isCan;
    }

    /**
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function sendCouponByIds($userId, $idArr): bool
    {
        $where = [
            ['id','in',$idArr]
        ];
        $coupon = Coupon::getInstance()->where($where)->select();
        if (empty($coupon)) {
            return false;
        }
        foreach ($coupon as $v) {
            $this->autoRelease($userId, $v);
        }
        return true;
    }

}
